/**
  ******************************************************************************
  * @file           
  * @author         古么宁
  * @brief          遥信相关处理流程，如总召唤等
  ******************************************************************************
  *
  * COPYRIGHT(c) 2019 GoodMorning
  *
  ******************************************************************************
  */
/* Includes ---------------------------------------------------*/// 
#include <string.h>

#include "iec10x.h"
#include "iec10x_link.h"
#include "iec10x_telesgnl.h" //telesignalling
#include "iec10x_event.h"
#include "iec10x_debug.h"

#include "../iec/devif.h"

#include "COT.h"
#include "ASDUTYP.h"

/* Private types ------------------------------------------------------------*/

// 召唤事件记录体，把它放这里是为了可以使用宏定义 iec101_summon_add 实现非 malloc 注册
struct iec_summon{
  struct iec_slist     node      ; ///< 召唤事件节点
  unsigned char        type      ; ///< ASDU 类型
  unsigned char        group     ; ///< 组 @see summon_grp_t
};

/// 正在进行的召唤缓存
struct slv_summon {
	struct iec_slist  * node     ;
	int                 group    ;
	int                 reading  ;
	int                 cot      ;
};


/* Private macro ------------------------------------------------------------*/
/* Private variables --------------------------------------------------------*/
/* Global  variables --------------------------------------------------------*/
/* Private function prototypes ----------------------------------------------*/


#if (!ENABLE_IEC10x_SLAVE)
	#define iec10xslv_summon_respond(...)
	int  iec10xslv_summon_add(iec10x_t * bus ,enum iecgrp grp ,unsigned char type) {}
	void iec10xslv_peridic_summon(iec10x_t * bus){}
#else

static void iec10xslv_summon_finish(iec10x_t * bus);
static void iec10xslv_summon_data(iec10x_t * bus);
static void iec10xslv_summon_confirm(iec10x_t * bus);

/**
  * @brief    检测一包数据最大发送个数，用户数据是否地址连续
  * @author   古么宁
  * @param    bus      : 总线
  * @param    addr     : 需要检测的数据的起始地址
  * @param    nums     : 需要检测的数据个数
  * @param    argsize  : 单个用户数据的 sizeof 长度
  * @return   返回 qualifier 值，包含了一包的最大发送个数和地址是否连续
*/
static int addrcheck(iec10x_t * bus,uint32_t *addr , int nums , int argsize)
{
	IEC_INDEX(bus->causelen,bus->cmnaddrlen);
	int addrSQ = 1 , addrSQnums = 0; 

	/* 假设地址连续，理论上一包最大能传输的信息体结构个数 */
	int readnum = (bus->pktmax - IEC_INFO - bus->infoaddrlen) / argsize ; 
	if (nums > 127) {
		nums = 127;
	}

	if (readnum > nums) {
		readnum = nums;
	}

	/* 判断后续的 readnum 个元素的地址是否连续 , addrSQnums 统计连续地址个数 */
	if ((1 + addr[0]) != addr[1])
		addrSQ = 0; 
	else 
	for (addrSQnums = 1 ; addrSQnums < readnum ; ++addrSQnums){  
		uint32_t prev = addr[addrSQnums - 1];
		if ((prev + 1) != (addr[addrSQnums])) {
			addrSQ = 0 ;
			break;
		}
	}

	if (!addrSQ) {
		/* 地址不连续，则需要重新计算当前包最大能发多少个元素，
		   如果按照地址连续的那部分点组包发送，比按照不连续的方式发要划算，
		   则依旧选择按照连续地址的方式发送，不过只发送地址连续的那部分 */
		int maxnums ;
		maxnums = (bus->pktmax - IEC_INFO)/(argsize + bus->infoaddrlen);
		if (maxnums > nums){
			maxnums = nums;
		}
		addrSQ = (addrSQnums > maxnums);
		readnum = addrSQ ? addrSQnums : maxnums;
	}

	return (readnum)|(addrSQ<<7);
}


/**
  * @brief    加载用户数据
  * @author   古么宁
  * @param    bus      : 总线
  * @param    dev      : 需要加载的数据所属的用户设备接口
  * @param    addr     : 需要加载的数据的起始地址
  * @param    nums     : 需要加载的数据个数
  * @param    SQ       : 是否按照地址连续的方式加载数据
  * @param    data     : 数据输出内存
  * @return   返回数据包长度
*/
static int load_data(iec10x_t * bus , struct iec_devif * dev ,
			uint32_t * addr , int nums, int SQ, unsigned char * data )
{
	unsigned char * info = data;

	if ( SQ ) {
		/* 地址连续的读取方式，仅需加载第一个地址值 */
		uint32_t infoaddr = addr[0] ; 
		for (int i = 0 ; i < bus->infoaddrlen ; ++i){
			*info++ = (unsigned char)((infoaddr >> (i * 8)) & 0x00ff);
		}
		for (int i = 0 ; i < nums ; ++i) { 
			dev->readfn(bus,infoaddr,info);
			info     += dev->argsize;
			infoaddr += 1;
		}
	}
	else 
	if (bus->infoaddrlen > 2){
		/* 信息体地址不连续时的读取方式 */
		uint32_t * infoaddr = addr; 
		for (int i = 0 ; i < nums ; ++i ) {
			*info++ = (*infoaddr >> 0 ) & 0x00ff ;
			*info++ = (*infoaddr >> 8 ) & 0x00ff ;
			*info++ = (*infoaddr >> 16) & 0x00ff ;
			dev->readfn(bus,*infoaddr,info);
			info     += dev->argsize;
			infoaddr += 1;
		}
	}
	else {
		uint32_t * infoaddr = addr; 
		for (int i = 0 ; i < nums ; ++i ) {
			*info++ = (*infoaddr >> 0 ) & 0x00ff ;
			*info++ = (*infoaddr >> 8 ) & 0x00ff ;
			dev->readfn(bus,*infoaddr,info);
			info     += dev->argsize;
			infoaddr += 1;
		}
	}

	return info - data ;
}



/**
  * @brief    总召唤结束帧
  * @author   古么宁
  * @param    bus      : 总线
  * @param    ASDUrx   : 接收到的 ASDU 数据包
  * @param    ASDUlen  : 接收到的 ASDU 数据包长度
  * @return   don't care
*/
static void iec10xslv_summon_finish(iec10x_t * bus)
{
	IEC_INDEX(bus->causelen,bus->cmnaddrlen);
	unsigned char ASDU[32] = {0};
	unsigned char linkctrl , *info ;
	struct slv_summon * summoning ;
	
	summoning = (struct slv_summon *)bus->operate.argv;

	ASDU[IEC_TYPE]          = C_IC_NA_1               ;
	ASDU[IEC_QUALIFIER]     = 0x01                    ; 
	ASDU[IEC_COT]           = COT_ACTIVATE_EXIT       ;
	ASDU[IEC_COT+1]         = bus->connectaddr & 0xff ;
	ASDU[IEC_COMMON_ADDR]   = bus->cmnaddr     & 0xff ;
	ASDU[IEC_COMMON_ADDR+1] = bus->cmnaddr     >> 8   ;


	info    = &ASDU[IEC_INFO + bus->infoaddrlen]  ;
	*info++ = summoning->group ; 

	memset(&bus->operate,0,sizeof(struct iec_do));
	if (bus->mode & IEC_101) {
		if (bus->mode & IEC_BALANCE) {
			int FCB = (bus->iec101.FCB == 0) ;
			bus->iec101.FCB = FCB;
			linkctrl  = IEC_CTRL(0,1,FCB,1,MASTER_TRANS);
			linkctrl |= (bus->mode & IEC_DIRECT) ;
		}
		else {
			linkctrl = IEC_CTRL(0,0,0,0,SLAVE_ACK);
		}
		iec101_protocol_send(bus,ASDU,info-ASDU,linkctrl);
	}
	else {
		iec104_protocol_send(bus,ASDU,info-ASDU,0);
	}
}


/**
  * @brief    总召唤数据帧，发送总召唤数据
  * @author   古么宁
  * @param    bus      : 总线
  * @return   don't care
*/
static void  iec10xslv_summon_data(iec10x_t * bus)
{
	IEC_INDEX(bus->causelen,bus->cmnaddrlen);

	unsigned char * ASDUtx= ASDU_TXBUFF(bus);
	unsigned char   linkctrl ;
	uint32_t *      addrlist = NULL;
	int             readnums , qualifier , record ;
	int             len, SQ;
	int             infonum  = 0;

	struct slv_summon * summoning ;
	struct iec_slist  * node = NULL;
	struct iec_summon * summon = NULL;
	struct iec_devif  *  dev   = NULL;

	summoning = (struct slv_summon *)bus->operate.argv;

	/* 获取当前召唤类型 */
	node = summoning->node ;
	do {
		if (!node) {
			if (summoning->cot == summoning->group)
				iec10xslv_summon_finish(bus);
			else
				memset(&bus->operate,0,sizeof(struct iec_do));
			return ;
		}

		summon = container_of(node , struct iec_summon ,node);
		if (summon->group != summoning->group){ 
			/* 如果已传输完同组数据，结束帧 */
 			iec10xslv_summon_finish(bus);
			return ;
		}

		/* 获取当前总召类型的应用数据接口，在 iec104slv_summon_add() 注册的时候已判断
		   应用接口合法性，此处不做判断。根据接口获取应用数据的信息地址列表和信息总个数 */
		dev = iec_devif_find(&bus->device,summon->type);
		dev->statefn(bus,&addrlist , &infonum); 
	}while(!infonum) ;


	/* 判断信息结构体地址是否连续。bus->operate.argv 记录了当前传输点位置 */
	record    = summoning->reading ;
	qualifier = addrcheck(bus,&addrlist[record],infonum - record,dev->argsize);
	SQ        = qualifier & 0x80 ;
	readnums  = qualifier - SQ ;
	ASDUtx[IEC_TYPE]          = summon->type            ;
	ASDUtx[IEC_QUALIFIER]     = qualifier               ;
	ASDUtx[IEC_COT]           = summoning->cot          ;
	ASDUtx[IEC_COT+1]         = bus->connectaddr & 0xff ;
	ASDUtx[IEC_COMMON_ADDR]   = bus->cmnaddr     & 0xff ;
	ASDUtx[IEC_COMMON_ADDR+1] = bus->cmnaddr     >> 8   ;

	/* 加载用户数据至 &ASDUtx[IEC_INFO] 内存中，返回数据长度 */
	len = load_data(bus,dev,&addrlist[record],readnums,SQ,&ASDUtx[IEC_INFO]);
	len += IEC_INFO ;
	/* 更新记录当前发送位置 */
	record += readnums;
	if (record >= infonum) {
		/* 已全部发送完当前数据类型 */
		summoning->node = node->next;
		summoning->reading = 0;
	}
	else {
		/* 尚未发送完当前数据类型，记录当前发送点 */
		summoning->reading = record;
	}

	if (bus->mode & IEC_101) {
		if (bus->mode & IEC_BALANCE) {  
			int FCB = (bus->iec101.FCB == 0) ;
			bus->iec101.FCB = FCB;
			linkctrl  = IEC_CTRL(0,1,FCB,1,MASTER_TRANS);
			linkctrl |= (bus->mode & IEC_DIRECT) ;
		}
		else {
			linkctrl = IEC_CTRL(0,0,1,0,SLAVE_ACK);
		}
		iec101_protocol_send(bus,ASDUtx,len,linkctrl);
	}
	else {
		iec104_protocol_send(bus,ASDUtx,len,0);
	}
}



/**
  * @brief    从机总召响应
  * @author   古么宁
  * @param    bus      : 总线
  * @param    ASDUrx   : 接收到的 ASDU 数据包
  * @param    ASDUlen  : 接收到的 ASDU 数据包长度
  * @return   don't care
*/
static void  iec10xslv_summon_confirm(iec10x_t * bus)
{
	IEC_INDEX(bus->causelen,bus->cmnaddrlen);
	uint8_t ASDUtx[32] = {0};
	unsigned char * info = &ASDUtx[IEC_INFO+ bus->infoaddrlen];
	unsigned char   linkctrl ;
	struct slv_summon * summoning ;

	summoning = (struct slv_summon *)bus->operate.argv;

	ASDUtx[IEC_TYPE]          = C_IC_NA_1               ;
	ASDUtx[IEC_QUALIFIER]     = 0x01                    ;
	ASDUtx[IEC_COT]           = COT_ACTIVATE_CONFIRM    ;
	ASDUtx[IEC_COT+1]         = bus->connectaddr & 0xff ;
	ASDUtx[IEC_COMMON_ADDR]   = bus->cmnaddr     & 0xff ;
	ASDUtx[IEC_COMMON_ADDR+1] = bus->cmnaddr     >> 8   ;

	/* 在 summon_respond() 中纪录 */
	*info++ = summoning->group;

	if (bus->mode & IEC_101) {
		if (bus->mode & IEC_BALANCE) {
			int FCB = (bus->iec101.FCB == 0) ;
			bus->iec101.FCB = FCB;
			linkctrl  = IEC_CTRL(0,1,FCB,1,MASTER_TRANS);
			linkctrl |= (bus->mode & IEC_DIRECT) ;
		}
		else {
			linkctrl = IEC_CTRL(0,0,1,0,SLAVE_ACK);
		}
		iec101_protocol_send(bus,ASDUtx,info - ASDUtx,linkctrl);
	}
	else {
		iec104_protocol_send(bus,ASDUtx,info - ASDUtx,0);
	}

	bus->operate.todo = iec10xslv_summon_data;
}




/**
  * @author   古么宁 
  * @brief    非平衡模式下的从机召唤响应
  * @param    bus      : 总线
  * @param    ASDUrx   : 接收到的 ASDU 数据包
  * @param    ASDUlen  : 接收到的 ASDU 数据包长度
  * @return   don't care
*/
static void iec10xslv_summon_respond(iec10x_t * bus , unsigned char * ASDU,int32_t ASDUlen)
{
	IEC_INDEX(bus->causelen,bus->cmnaddrlen);
	struct  iec_summon * summon;
	struct  slv_summon * summoning ;
	unsigned char linkctrl ;
	unsigned char group = ASDU[IEC_INFO + bus->infoaddrlen];

	/* 先获取需要上送的数据类型。数据类型在 iec10xslv_summon_addtype()
	   中注册于链表中，先获取链表节点，存于 argv[] */
	struct iec_slist  * node ;
	for (node = bus->summon.next; node ; node = node->next) {
		summon = container_of(node,struct iec_summon,node);
		if (summon->group == group) // 找到同组位置
			break ;
		else 
		if (summon->group > group) {// 无此组数据响应
			node = NULL;
			break;
		}
	}

	memset(&bus->operate,0,sizeof(struct iec_do));
	summoning = (struct slv_summon *)bus->operate.argv;
	summoning->node    = node           ;
	summoning->group   = group          ;
	summoning->reading = 0              ;
	summoning->cot     = group          ;
	
	if (bus->mode & IEC_101) {
		if (bus->mode & IEC_BALANCE) {
			linkctrl  = IEC_CTRL(0,0,0,0,SLAVE_OK);
			linkctrl |= (bus->mode & IEC_DIRECT)  ;
			iec101_protocol_send(bus,NULL,0,linkctrl);
			bus->iec101.todo  = iec10xslv_summon_confirm  ;
		}
		else {
			linkctrl = IEC_CTRL(0,0,1,0,SLAVE_OK) ;
			iec101_protocol_send(bus,NULL,0,linkctrl);
		}
	}

	bus->operate.todo  = iec10xslv_summon_confirm  ;
}


/**
  * @brief    从站添加总召响应类型
  * @param    bus      : 总线
  * @param    grp      : 响应组， @see enum iecgrp
  * @param    type     : 响应类型， @see enum asdutype
  * @return   成功返回0 ， 否则返回其他
*/
int iec10xslv_summon_add(iec10x_t * bus ,enum iecgrp grp ,unsigned char type)
{
	int    newindex ,index;
	struct iec_devif *   dev      ;
	struct iec_slist  ** node     ;
	struct iec_summon *  newsummon, *exist ;

	if (bus->mode & IEC_MASTER) {
		return -1;
	}

	/* 如果没有应用数据接口，不进行注册 */
	dev = iec_devif_find(&bus->device,type);
	if (NULL == dev || NULL == dev->statefn || NULL == dev->readfn) {
		return -1;
	}

	/* 查找当前类型所在位置 */
	newindex = (grp << 8)|type;
	node     = &bus->summon.next;
	while(*node) {
		exist = container_of(*node,struct iec_summon,node);
		index = (exist->group << 8) | exist->type;
		if (newindex > index) {
			break;
		}
		else
		if (newindex == index) {
			return -1;
		}
		else {
			node = &((*node)->next);
		}
	}

	/* 新建插入 */
	newsummon = iec_malloc(sizeof(struct  iec_summon));
	if (!newsummon) {
		return -1;
	}

	newsummon->group     = grp;
	newsummon->type      = type ;
	newsummon->node.next = *node;
	*node = &newsummon->node;
	return 0;

}


/**
  * @brief    启动周期上送
  * @author   古么宁
  * @param    bus      : 总线
  * @return   don't care
*/
void iec10xslv_peridic_summon(iec10x_t * bus)
{
	struct iec_slist * node  = bus->summon.next;
	struct slv_summon * summoning ;
	struct iec_summon * summon ;

	//memset(&bus->operate,0,sizeof(struct iec_do));

	for ( ; node ; node = node->next) { 
		summon = container_of(node,struct iec_summon,node);
		if (summon->group == IEC_GRP_ALL) {// 找到同组位置
			break ;
		}
		else 
		if (summon->group > IEC_GRP_ALL) {// 无此组数据响应
			node = NULL;
			break;
		}
	}

	if (node){
		summoning = (struct slv_summon *)bus->operate.argv;
		summoning->node  = node       ;
		summoning->group = IEC_GRP_ALL;
		summoning->cot   = COT_CYCLE  ;
		bus->operate.todo = iec10xslv_summon_data;
		if (bus->mode & IEC_BALANCE)
			iec10xslv_summon_data(bus);
	}
}

#endif /** #if (!ENABLE_IEC10x_SLAVE) */

// -------------------------------- 主机总召相关 --------------------------------


#if (!ENABLE_IEC10x_MASTER)

	/* 不使能主站功能时 */
	#define iec10xmst_summon_respond(...)
	void iec10xmst_summon_req(iec10x_t * bus , enum iecgrp  group){}
	void iec10xmst_summon(iec10x_t * bus , enum iecgrp  group){}

#else

/**
  * @author   古么宁 
  * @brief    主机召唤响应，收到来自从机的响应包
  * @param    bus      : 总线
  * @param    ASDUrx   : 接收到的 ASDU 数据包
  * @param    ASDUlen  : 接收到的 ASDU 数据包长度
  * @return   don't care
*/
static void iec10xmst_summon_respond(iec10x_t * bus , unsigned char * ASDU,int32_t ASDUrxlen)
{
	//IEC_INDEX(bus->causelen,bus->cmnaddrlen);
	switch (ASDU[IEC_COT]){
	case COT_ACTIVATE_CONFIRM : //激活确认包
		iec10x_msg(bus,"ready to read data.\r\n");
		break ;

	case COT_ACTIVATE_EXIT :    //激活结束包
		bus->busy &= ~IEC10x_SUMMON ;
		iec10x_msg(bus,"data end\r\n");
		if (!(bus->mode & IEC_101)) {
			/* 104 下使能更新滑动窗口 */
			bus->onlinet = iec_timestamp - bus->t2;
		}
		break;
	}
}


/**
  * @brief    主机设备请求召唤数据。
  *           此处涉及到线程安全问题，不马上进行发送包操作。
  *           因为在调用此接口的同时，有可能刚好与轮询任务相冲，直接发送会在发送接口上会产生冲突。
  *           而轮询任务中不建议依赖互斥量，因此系统先缓存此事件包，到下一次轮询的时候执行发送。
  * @param    bus    : 需要解析的总线结构体 
  * @param    group  : 请求组，参考@see summon_grp_t
  * @return   don't care
*/
static void iec10xmst_summon_pkt(iec10x_t * bus , void * arg)
{
	IEC_INDEX(bus->causelen,bus->cmnaddrlen);
	unsigned char * ASDU = (unsigned char *)arg;
	unsigned char   len = IEC_INFO + bus->infoaddrlen + 1 ;
	unsigned char   linkctrl = 0;
	
	if (bus->mode & IEC_101) {
		if (bus->mode & IEC_BALANCE) {
			int FCB = (bus->iec101.FCB == 0) ;
			bus->iec101.FCB = FCB;
			linkctrl  = IEC_CTRL(0,1,FCB,1,MASTER_TRANS);
			linkctrl |= (bus->mode & IEC_DIRECT) ;
		}
		else {
			linkctrl = IEC_CTRL(0,1,0,1,MASTER_TRANS) ;
		}
		iec101_protocol_send(bus,ASDU,len,linkctrl);
	}
	else {
		iec104_protocol_send(bus,ASDU,len,0);
	}

	bus->busy |= IEC10x_SUMMON ;
	iec10x_msg(bus,"summon.\r\n");
}


/**
  * @brief    主机设备请求召唤数据。
  *           此处涉及到线程安全问题，不马上进行发送包操作。
  *           因为在调用此接口的同时，有可能刚好与轮询任务相冲，直接发送会在发送接口上会产生冲突。
  *           而轮询任务中不建议依赖互斥量，因此系统先缓存此事件包，到下一次轮询的时候执行发送。
  * @param    bus    : 需要解析的总线结构体 
  * @param    group  : 请求组，参考@see summon_grp_t
  * @return   don't care
*/
void iec10xmst_summon_req(iec10x_t * bus , enum iecgrp  group)
{
	if (!bus->connected) {
		return ;
	}

	if (group == IEC_GRP_ALL) {
		bus->periodt = iec_timestamp - bus->data_period ;
	}
	else {
		IEC_INDEX(bus->causelen,bus->cmnaddrlen);
		unsigned char ASDUtx[16];
		unsigned char * info = &ASDUtx[IEC_INFO]  ;

		ASDUtx[IEC_TYPE]          = C_IC_NA_1               ;
		ASDUtx[IEC_QUALIFIER]     = 0x01                    ;
		ASDUtx[IEC_COT]           = COT_ACTIVATE            ;
		ASDUtx[IEC_COT+1]         = bus->connectaddr & 0xff ;
		ASDUtx[IEC_COMMON_ADDR]   = bus->cmnaddr     & 0xff ;
		ASDUtx[IEC_COMMON_ADDR+1] = bus->cmnaddr     >> 8   ;

		for (int i = 0 ; i < bus->infoaddrlen ; ++i) {
			*info++ = 0;
		}
		*info++ = group ;

		iec10xmst_event(bus,iec10xmst_summon_pkt,ASDUtx,info-ASDUtx);
	}
}


/**
  * @brief    主机设备发送召唤数据请求数据包 
  * @param    bus    : 需要解析的总线结构体 
  * @param    group  : 请求组，参考@see summon_grp_t
  * @return   don't care
*/
void iec10xmst_summon(iec10x_t * bus , enum iecgrp group )
{
	IEC_INDEX(bus->causelen,bus->cmnaddrlen);
	uint8_t ASDU[16]; //ASDU 信息
	uint8_t * info = &ASDU[IEC_INFO]  ;
	unsigned char   linkctrl = 0;

	ASDU[IEC_TYPE]          = C_IC_NA_1               ;
	ASDU[IEC_QUALIFIER]     = 0x01                    ;
	ASDU[IEC_COT]           = COT_ACTIVATE            ;
	ASDU[IEC_COT+1]         = bus->connectaddr & 0xff ;
	ASDU[IEC_COMMON_ADDR]   = bus->cmnaddr     & 0xff ;
	ASDU[IEC_COMMON_ADDR+1] = bus->cmnaddr     >> 8   ;

	for (int i = 0 ; i < bus->infoaddrlen ; ++i) {
		*info++ = 0;
	}
	*info++ = group ;

	if (bus->mode & IEC_101) {
		if (bus->mode & IEC_BALANCE) {
			int FCB = (bus->iec101.FCB == 0) ;
			bus->iec101.FCB = FCB;
			linkctrl  = IEC_CTRL(0,1,FCB,1,MASTER_TRANS);
			linkctrl |= (bus->mode & IEC_DIRECT) ;
		}
		else {
			linkctrl = IEC_CTRL(0,1,0,1,MASTER_TRANS) ;
		}
		iec101_protocol_send(bus,ASDU,info-ASDU,linkctrl);
	}
	else {
		iec104_protocol_send(bus,ASDU,info-ASDU,0);
	}

	/* 置位总线状态，在接收到结束帧后清零 */
	bus->busy |= IEC10x_SUMMON ;
}

#endif /** #if (!ENABLE_IEC10x_MASTER) */

/**
  * @brief    总召响应
  * @author   古么宁
  * @param    bus      : 总线
  * @param    ASDUrx   : 接收到的 ASDU 数据包
  * @param    ASDUlen  : 接收到的 ASDU 数据包长度
  * @return   don't care
*/
void iec10x_summon_respond(iec10x_t * bus , unsigned char * ASDU,int ASDUlen)
{
	if (bus->mode & IEC_MASTER) 
		iec10xmst_summon_respond( bus , ASDU, ASDUlen);
	else 
		iec10xslv_summon_respond( bus , ASDU, ASDUlen);
}
